//
//  Moya+Extension.swift
//  Lease_IOS
//
//  Created by Mr.wang on 2018/12/20.
//  Copyright © 2018 Mr.wang. All rights reserved.
//

import Moya
import RxSwift
import Alamofire

extension Response {
    
    static var none: Response {
        return Response.init(statusCode: 0, data: Data())
    }
    
    var code: Int {
        let code = jsonDictionary["code"] as? Int
        return code ?? 9999
    }
    
    var isSuccess: Bool {
        return code == 200
    }
    
    var msg: String {
        let msg = jsonDictionary["msg"] as? String
        return msg ?? "数据解析失败".localized
    }
    
    var jsonDictionary: NSDictionary {
        do {
            let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? NSDictionary
            return json ?? NSDictionary()
        } catch {
            return NSDictionary()
        }
    }
    
}

extension Task {
    var parameters: [String: String] {
        switch self {
        case .requestParameters(let parameters, _):
            return parameters as? [String: String] ?? [:]
        default:
            return [:]
        }
    }
}

extension Error {
    
    var code: Int {
        return (self as NSError).code
    }
    
    var domain: String {
        return (self as NSError).domain
    }
    
}

extension MoyaError {
    
    var underlyingError: Error? {
        switch self {
        case .underlying(let error, _):
            if let afError = error as? Alamofire.AFError,
                let underlyingError = afError.underlyingError {
                return underlyingError
            }
            return error
        default:
            return nil
        }
    }
    
    var isCancelled: Bool {
        if let error = underlyingError {
            return error.code == NSURLErrorCancelled
        }
        return false
    }
    
    var notConnected: Bool {
        if let error = underlyingError {
            return error.code == NSURLErrorNotConnectedToInternet
        }
        return false
    }
}

extension ObservableType where Element == Response {
    
    public func filterCode200() -> Observable<Response> {
        return self.filter{ $0.isSuccess }
    }
    
    public func trackError(_ codes: [Int] = [],
                           closure: @escaping (Int) -> () = {_ in}) -> Observable<Response> {
        return self.errorWhenCodeNot200()
            .catchError({ (error) -> Observable<Response> in
                guard let requestError = error as? RequestError,
                    codes.contains(requestError.code) else {
                        APPHud.shared.showError(status: error.localizedDescription)
                        return Observable.just(Response.none)
                }
                closure(requestError.code)
                return Observable.just(Response.none)
            })
    }
    
    func handleNormalError() -> Observable<Response> {
        return self.catchError({ (error) -> Observable<Response> in
            APPHud.shared.showError(status: error.localizedDescription)
            return Observable.just(.none)
        })
    }
    
}

extension PrimitiveSequence where Trait == SingleTrait, Element == Response {
    
    public func filterCode200() -> Observable<Response> {
        return self.asObservable().filterCode200()
    }
    
}
